/**
 * @file sline.c
 * @author zhuxuanlin (xuanlinzhu@qq.com)
 * @brief sline命令行组件的功能实现
 * 
 * @copyright Copyright (c) 2023
 * 
 */
#include <string.h>
#include <stdarg.h>
#include "sline.h"

#ifdef _WIN32
	#include <stdio.h>
#endif

/**
 * @brief 适配龙芯的GCC编译器
 * 龙芯GCC编译的工具链会自动生成代码段的开始和结束符
 */
#if (SL_LS2K1000_EX)
extern sline_cmd_code_t __start_cmd_list[];
extern sline_cmd_code_t __stop_cmd_list[];
static sline_cmd_code_t * sl_cmd_list = __start_cmd_list;
#endif

/*创建环境,降低代码复杂程度,不支持多对象*/
static sl_env_t sl_env = {-1};

/*创建命令列表*/
static sline_cmd_t sl_cmds[SL_CMDS_LEN] = {
	{.name = "", .func = NULL,.desc = ""}
};

/*指令数量*/
static unsigned int sl_cmds_num = 0;

#if (SL_KEYWORD_ENABLE)
/* 创建关键字列表 */
static sl_keys_st sl_keys = {
	.num = 0
};
#endif

#if (SL_OUTPUT_ENABLE)
/* 定义是否移交输入至外部接口,默认不移交 */
static sl_output_t sl_output  = {.flag = -1,.output = NULL};
#endif 

/**
 * @brief 在环境中注册指令
 * 		  注意调用在sl_create之前，否则不会被注册
 * @param name 指令名字
 * @param func 指令函数指针
 * @param desc 指令目的
 * @return int 	0：正常 -1:失败
 */
int sl_cmd_export_pre(char* name,void * func,char *desc)                               
{
	if(sl_cmds_num >= SL_CMDS_LEN)
	{
		return -1;
	}
	memcpy((void *)sl_cmds[sl_cmds_num].name,name,strlen(name));        
	memcpy((void *)sl_cmds[sl_cmds_num].desc,desc,strlen(desc));     
	sl_cmds[sl_cmds_num].func = func;   
	sl_cmds_num++;
	return 0;                     
}

#if(SL_KEYWORD_ENABLE)
/**
 * @brief 在环境中添加关键字
 * 		  
 * @param key  关键字内容
 * 
 * @return int 	0：正常 -1:失败
 */
int sl_key_add(char *key)
{
	if(key == NULL)
	{
		return -1;
	}
	if(strlen(key) <= 0)
	{
		return -1;
	}
	if(sl_keys.num < SL_KEYWORD_NUM)
	{
		if(strlen(key) > SL_KEYWORD_LEN)
		{
			return -1;
		}
		sprintf(sl_keys.keys[sl_keys.num],"%s",key);
		sl_keys.num++;
		return 0;		
	}
	return -1;
}

/**
 * @brief 在环境中批量添加关键字
 * 		  
 * @param keys  关键字内容
 * 
 * @return int 	0：正常 -1:失败
 */
int sl_keys_add(char **keys , int num)
{
	int i = 0 ;
	int ret = 0;
	if(keys == NULL)
	{
		return -1;
	}
	for(i = 0 ;i < num ; i++)
	{
		if(sl_key_add(keys[i]) < 0)
		{
			ret --;
		}
	}
	return ret ;
}
#endif

/**
 * @brief 组件打印函数
 * 
 * @param format 
 * @param ... 
 * @return int 
 */
int sl_printf(const char *format,...)
{
	char buff[SL_PRINTF_NUM] = {0};
	int i = 0;
	va_list args;
	va_start(args,format);
	int len = vsnprintf(buff,sizeof(buff),format,args);
	va_end(args);
	for(i = 0 ;i<len;i++)
	{	
		sl_env.func.putc(buff[i] );	
	}
	return 0;
}

/**
 * @brief 命令检测函数
 * 			检测是不是命令列表中的函数
 * @param cmd 指令
 * @return int 0：正常 -1:失败
 */
static int sl_cmd_para(char * cmd)
{
	int i,ret,argc = 0;
	/* [zxl 2023-10.30][YKGCVV-280]将argv长度+1,避免数据溢出[start] */
	char * argv[SL_CMD_ARGC_MAX + 1] = {0};
	/* [zxl 2023-10.30][YKGCVV-280]将argv长度+1,避免数据溢出[end] */
	
	argv[argc] = strtok(cmd," ");
	while (argv[argc] !=NULL && argc <SL_CMD_ARGC_MAX)
	{
		argc++;
		argv[argc] = strtok(NULL," ");
	}
	// 检测到没有任何指令输入
	if(argc == 0)
	{
		return -1;
	}
	for (i = 0 ;i<sl_cmds_num ;i++)
	{
		if(strcmp(sl_cmds[i].name,argv[0]) ==  0)
		{
			ret = sl_cmds[i].func(argc ,argv);
			if(ret<0)
			{
				sl_printf("%s Run Error!\r\n",argv[0]);	
			}
			return 0;
		}
	}
	sl_printf("This isn't a cmd : %s\r\n",argv[0]);
	return -1;
}

/**
 * @brief 显示所有命令
 * 
 * @param argc 
 * @param argv 
 * @return int 
 */
int sl_show_allcmd(int argc,char * argv[])
{
	int i;
	for (i = 0 ;i<sl_cmds_num ;i++)
	{
		sl_printf("	%s: %s\r\n",sl_cmds[i].name,sl_cmds[i].desc);
	}
	return 0;
}

/**
 * @brief 显示输入历史
 * 
 * @param argc 
 * @param argv 
 */
static void sl_show_his(int argc,char * argv[])
{
	int i;
	sl_printf("	input history:\r\n");
	for (i = 0 ;i<SL_HIS_FIFO_NUM ;i++)
	{
		if(sl_env.his[i].len != 0)
		{
			sl_printf("	[%d]: %s\r\n",i,sl_env.his[i].buff);
		}
		else
		{
			break;
		}
	}
}

/**
 * @brief 存储输入的历史字符串
 * 
 * @param cmd 
 */
static void sl_add_his_cmd(sl_dis_t *cmd)
{
	if(cmd->len != 0)
	{
		int i =SL_HIS_FIFO_NUM -1;
		for( ;i>0;i--)
		{
			memcpy(&sl_env.his[i],&sl_env.his[i-1],sizeof(sl_dis_t));
		}
		memcpy(&sl_env.his[0],cmd,sizeof(sl_dis_t));
	}
}

/**
 * @brief 显示历史记录中的字符串
 * 
 * @param cur 字符串的序号
 */
static void sl_dis_his_cmd(int cur)
{
	memcpy(&sl_env.dis,&sl_env.his[cur],sizeof(sl_dis_t));
	sl_env.dis_cursor = sl_env.his[cur].len;
	sl_printf("%s",sl_env.dis.buff);
}

/**
 * @brief 移动游标至末尾
 * 
 */
static void sl_cursor_move_end(void)
{
	int i = 0;
	for(i = sl_env.dis_cursor ; i < sl_env.dis.len ;i++)
	{
		sl_env.func.putc(sl_env.dis.buff[i]);
	}
	sl_env.dis_cursor = sl_env.dis.len;
}

/**
 * @brief 创建新的一行对sl对象的数据处理
 * 
 */
static void sl_newline(void)
{
	memset(sl_env.dis.buff,0,SL_HIS_FIFO_LEN);
	sl_env.dis.len = 0;
	sl_env.dis_cursor = 0;
	sl_env.his_cursor = 0;
}

/**
 * @brief 换行操作
 * 
 */
static void sl_enter(void)
{
	sl_printf("\r\n");
}

/**
 * @brief 退格操作
 * 
 * @param cnt 退格的个数
 */
static void sl_backspace(int cnt)
{
	while (cnt --)
	{
		if(sl_env.dis_cursor>0)
		{
			if(sl_env.dis_cursor == sl_env.dis.len) /*末尾删除*/
			{
				sl_env.dis.len--;
				sl_env.dis_cursor--;
				sl_env.dis.buff[sl_env.dis_cursor] = 0x00;
				sl_env.func.putc('\b');
				sl_env.func.putc(' ');
				sl_env.func.putc('\b');
			}
			else /*中间删除字符*/
			{
				int i;
				sl_env.func.putc('\b');
				sl_env.dis_cursor--;
				/*缓存中后面的字符前移*/
				for(i = sl_env.dis_cursor;i<sl_env.dis.len - 1;i++)
				{
					sl_env.dis.buff[i] = sl_env.dis.buff[i+1];
				}		
				sl_env.dis.buff[sl_env.dis.len-1] = 0x00;
				sl_env.dis.len--;
				/*打印后续字符*/
				for(i = sl_env.dis_cursor;i<sl_env.dis.len;i++)
				{
					sl_env.func.putc(sl_env.dis.buff[i]);
				}
				sl_env.func.putc(' ');
				sl_env.func.putc('\b');
				for(i = sl_env.dis_cursor;i<sl_env.dis.len;i++)
				{
					sl_env.func.putc('\b');
				}
			}
		}
	}
}

/**
 * @brief 指令匹配的函数
 * 
 * @param cmd 输入的指令
 * @return char* 返回的对应指令的字符串
 */
static char * sl_matching_cmd(sl_dis_t * cmd)
{
	int i = 0,j = 0;
	int notice_num = 0;
	int notice[ SL_NOTICE_NUM ] = {0};

#if(SL_KEYWORD_ENABLE)
	int offset = 0;
	/* 检测是否有多段输入，有多段输入则匹配关键字 */
	for(i = cmd->len -1 ;i>=0 ;i--)
	{
		if(*(char*)(cmd->buff+i) == ' ')
		{
			offset = i +1;
			break;
		}
	}
	if(offset == cmd->len)
	{
		sl_printf("\r\n");
		for(i = 0 ;i< (sl_keys.num > SL_NOTICE_NUM?SL_NOTICE_NUM:sl_keys.num);i++)
		{
			sl_printf("%s ",sl_keys.keys[i]);
		}
		sl_printf("\r\n");
		sl_printf(SL_HEADER);
		sl_printf("%s",sl_env.dis.buff);
		return NULL;
	}
	/* 存在多段输入 检索关键字库 */
	if(offset > 0)
	{
		for(i = 0 ;i<sl_keys.num;i++)
		{
			if(strncmp(sl_keys.keys[i],(char *)(cmd->buff + offset ),cmd->len - offset) == 0)
			{
				if(notice_num < SL_NOTICE_NUM)
				{
					notice[notice_num] = i;
					notice_num++;
				}
				else
				{
					break;
				}
			}
		}
		if(notice_num == 1)
		{
			if(strlen(sl_keys.keys[notice[0]])+offset > (SL_HIS_FIFO_LEN + 1))
			{
				return NULL;
			}
			/* 拼接字符串 */
			sprintf((char *)(cmd->buff + offset),"%s",sl_keys.keys[notice[0]]);
			return (char*)cmd->buff;
		}
		if(notice_num > 1)
		{
			/* 寻找公共字段并补全 */
			for(i = 0 ;i<SL_KEYWORD_LEN;i++)
			{
				for(j = 1 ;j<notice_num;j++)
				{
					if(sl_keys.keys[notice[0]][i] != sl_keys.keys[notice[j]][i])
					{
						break;
					} 
				}
				if(j != notice_num)
				{
					break;
				}
			}
			/* 没有公共字段补全 */
			if( i > (cmd->len - offset))
			{
				memcpy((char *)(cmd->buff + offset),sl_keys.keys[notice[0]],i);
				return (char*)cmd->buff;
			}
			else
			{
				sl_printf("\r\n");
				for(i = 0 ;i<notice_num;i++)
				{
					sl_printf("%s ",sl_keys.keys[notice[i]]);
				}
				sl_printf("\r\n");
				sl_printf(SL_HEADER);
				sl_printf("%s",sl_env.dis.buff);
				return NULL;
			}
		}
	}
#endif
	/* 没有多段输入,则匹配指令 */
	for(i = 0 ;i<sl_cmds_num;i++)
	{
		if(strncmp(sl_cmds[i].name,cmd->buff,cmd->len) == 0)
		{
			if(notice_num < SL_NOTICE_NUM)
			{
				notice[notice_num] = i;
				notice_num++;
			}
			else
			{
				break;
			}
		}
	}
	if(notice_num == 1)
	{
		return (char*)sl_cmds[notice[0]].name;
	}
	if(notice_num > 1)
	{
		/* 寻找公共字段并补全 */
		for(i = 0 ;i<SL_CMD_NAME_LEN;i++)
		{
			for(j = 1 ;j<notice_num;j++)
			{
				if(sl_cmds[notice[0]].name[i] != sl_cmds[notice[j]].name[i])
				{
					break;
				} 
			}
			if(j != notice_num)
			{
				break;
			}
		}
		/* 没有公共字段补全 */
		if( i > cmd->len)
		{
			memcpy((char *)cmd->buff,sl_cmds[notice[0]].name,i);
			return (char*)cmd->buff;
		}
		else
		{
			sl_printf("\r\n");
			for(i = 0 ;i<notice_num;i++)
			{
				sl_printf("%s ",sl_cmds[notice[i]].name);
			}
			sl_printf("\r\n");
			sl_printf(SL_HEADER);
			sl_printf("%s",sl_env.dis.buff);
			return NULL;
		}

	}
	return NULL;
}

/**
 * @brief tap操作
 * 
 */
static void sl_tap(void)
{
	if(sl_env.dis.len == 0)
	{
		sl_enter();
		sl_newline();
		sl_show_allcmd(0,NULL);
		sl_printf(SL_HEADER);
	}
	else if(sl_env.dis.len > 0)
	{
		char * cmd = NULL;
		int cmd_len,i = 0;
		/* 创建临时缓存 */
		sl_dis_t dis_tmp = { 0 };
		memcpy(&dis_tmp,&sl_env.dis,sizeof(dis_tmp) );
		cmd = sl_matching_cmd(&dis_tmp);
		/*补全指令*/
		if(cmd != NULL )
		{
			cmd_len = strlen(cmd);
			if(sl_env.dis.len < cmd_len)
			{
				sl_cursor_move_end();
				for(i = sl_env.dis.len;i<cmd_len;i++)
				{
					sl_env.func.putc(cmd[i]);
				}
				memcpy(sl_env.dis.buff,cmd,cmd_len);
				sl_env.dis.len = cmd_len;
				sl_env.dis_cursor = cmd_len;
			}
		}
	}
}

/**
 * @brief 上键
 * 
 */
static void sl_up(void)
{
	if(sl_env.his_cursor<SL_HIS_FIFO_NUM  )
	{
		sl_cursor_move_end();
		sl_backspace(sl_env.dis.len);
		sl_dis_his_cmd(sl_env.his_cursor);
		if(sl_env.his[sl_env.his_cursor+1].len != 0)
		{
			sl_env.his_cursor++;
		}
	}
}

/**
 * @brief 下键
 * 
 */
static void sl_down(void)
{
	if(sl_env.his_cursor>0)
	{
		sl_cursor_move_end();
		sl_backspace(sl_env.dis.len);
		sl_env.his_cursor--;
		sl_dis_his_cmd(sl_env.his_cursor);	
	}
	else if(sl_env.his_cursor == 0)
	{
		sl_backspace(sl_env.dis.len);
		sl_newline();
	}
}

/**
 * @brief 光标左移
 * 
 */
static void sl_left(void)
{
	if(sl_env.dis_cursor > 0)
	{
		sl_env.dis_cursor --;
		sl_env.func.putc('\b');
	}
}

/**
 * @brief 光标右移
 * 
 */
static void sl_right(void)
{
	if(sl_env.dis_cursor < sl_env.dis.len)
	{
		sl_env.func.putc(sl_env.dis.buff[sl_env.dis_cursor]);
		sl_env.dis_cursor ++;
	}
}

/**
 * @brief 正常的输入字符处理
 * 
 * @param c 输入字符
 */
static void sl_normal(char c)
{
	if(sl_env.dis.len<SL_HIS_FIFO_LEN)
	{
		if(sl_env.dis_cursor == sl_env.dis.len) /*末尾添加字符*/
		{
			sl_env.func.putc(c);
			sl_env.dis.buff[sl_env.dis_cursor] = c;
			sl_env.dis.len++;
			sl_env.dis_cursor++;
		}
		else	/*中间添加字符*/
		{
			int i;
			/*缓存中后面的字符后移*/
			for(i = sl_env.dis.len;i>sl_env.dis_cursor;i--)
			{
				sl_env.dis.buff[i] = sl_env.dis.buff[i-1];
			}		
			sl_env.func.putc(c);	
			sl_env.dis.buff[sl_env.dis_cursor] = c;
			/*光标右移一位*/
			sl_env.dis_cursor++;
			sl_env.dis.len++;
			/*打印后续字符*/
			for(i = sl_env.dis_cursor;i<sl_env.dis.len;i++)
			{
				sl_env.func.putc(sl_env.dis.buff[i]);
			}
			for(i = sl_env.dis_cursor;i<sl_env.dis.len;i++)
			{
				sl_env.func.putc('\b');
			}				
		}
	}
}

/**
 * @brief 对正常输入字符的范围限定
 * 
 * @param in 输入字符
 * @return int 
 */
static int sl_normal_input(unsigned char in)
{
	/* 大部分是非法字符 */
	if( in > 0x7f )
	{
		return -1;
	}
#if(SL_LS2K1000_EX == 1)
	/* 针对ls2k1000的补丁，否则方向按键无法使用 */
	if( in < 0x20)
	{
		return -1;
	}
	
	if(in == 0x5b)
	{
		return -1;
	}
#endif
	/* 嵌入式部分已经通过删除字符实现 方向键，取消部分字符限制*/
	return 0;
}

/**
 * @brief 读取完整一行的输入
 * 
 * @param dis  输入缓存
 * @return int 
 */
static int sl_readline(sl_dis_t *dis)
{
	for(;;)
	{
		int fd= sl_env.func.getc();
		if(fd<0)
		{
				return -1;
			}
		sl_env.wkey_val = (sl_env.wkey_val<<8)|((unsigned char)fd);
		
		if((unsigned int)(sl_env.wkey_val&0x000000FF) == '\r')/*命令结束*/
		{
			sl_enter();
			return 1;
		}
		else if((unsigned int)(sl_env.wkey_val&0x000000FF) == '\t')/*tap命令*/
		{
			sl_tap();
			return 0;
		}
		else if(((unsigned int)(sl_env.wkey_val&0x000000FF) == '\b')||
				((unsigned int)(sl_env.wkey_val&0x000000FF) == 0x7f))/*退格命令*/
		{
			sl_backspace(1);	
		}
	#if  (SL_LS2K1000_EX ||  SL_RM48_EX)
		else if((unsigned int)(sl_env.wkey_val&0x00FFFFFF) == 0x1b5b41)/*up*/
		{
			sl_up();	
		}
		else if((unsigned int)(sl_env.wkey_val&0x00FFFFFF) == 0x1b5b42)/*down*/
		{
			sl_down();	
		}
		else if((unsigned int)(sl_env.wkey_val&0x00FFFFFF) == 0x1b5b44)/*left*/
		{
			sl_left();	
		}
		else if((unsigned int)(sl_env.wkey_val&0x00FFFFFF) == 0x1b5b43)/*right*/
		{
			sl_right();	
		}
	#endif
	#if (SL_WIN_EX)
		else if((unsigned int)(sl_env.wkey_val&0x0000FFFF) == 0xe048)/*up*/
		{
			sl_up();	
		}
		else if((unsigned int)(sl_env.wkey_val&0x0000FFFF) == 0xe050)/*down*/
		{
			sl_down();	
		}
		else if((unsigned int)(sl_env.wkey_val&0x0000FFFF) == 0xe04b)/*left*/
		{
			sl_left();	
		}
		else if((unsigned int)(sl_env.wkey_val&0x0000FFFF) == 0xe04d)/*right*/
		{
			sl_right();	
		}
	#endif
		else if(sl_normal_input((unsigned int)(sl_env.wkey_val&0x000000FF)) == 0)/*正常输入字符*/
		{
			sl_normal(fd);
		}
		else
		{
			/*非常规字符*/
	}

	}
	return 0;
}


/**
 * @brief 检测输入字符串是否为合法指令
 * 
 * @param dis  输入缓存
 * @return int 0：正常 -1:失败
 */
static int sl_check_cmd(sl_dis_t *dis)
{
	int i = 0;
	// 检测长度是否正常
	if(dis->len <= 0)
	{
		return -1;
	}
	// 检测输入是否为全空格
	for(i = 0;i < dis->len; i++)
	{
		if(dis->buff[i] != ' ')
		{
			return 0;
		}
	}
	return -1;
}

#if (SL_OUTPUT_ENABLE)
/**
 * @brief 设置是否移交输入至外部接口
 * 
 * @param flag  设置flag 0<则放弃接管 ≥0启用外部接管
 */
int sl_output_set(sl_output_t * op)
{
	if(op->flag < 0)
	{
		sl_output.flag = -1;
		sl_output.output = NULL;
		return 0;
	}
	else
	{
		sl_output.flag = 0;
	}

	if(op->output != NULL)
	{
		sl_output.output = op->output;
	}
	else
	{
		return -1;
	}
	return 0;
}

/**
 * @brief 检测是否移交输入至外部接口
 * 
 * @return int 0：正常 -1:失败
 */
static int sl_output_check(void)
{
	if(sl_output.flag == 0 && sl_output.output != NULL)
	{
		return sl_output.flag;
	}
	return -1;
}
#endif

/**
 * @brief 等待处理命令输入
 * 
 * @return int 0：正常 -1:失败
 */
int sl_waitcmd (void)
{
	if(sl_env.status != 0)
	{
		return -1;
	}
	if(sl_readline(&sl_env.dis) == 1)
	{
		// 长度检测 全空格检测
		if(sl_check_cmd(&sl_env.dis) >= 0 )
		{
			// 正常指令加入输入历史
			sl_add_his_cmd(&sl_env.dis);
		#if (SL_OUTPUT_ENABLE)
			// 检测是否外部接管
			if(sl_output_check() < 0)
			{
				// 输入字符串处理，以回车结束 
				sl_cmd_para(sl_env.dis.buff);
			}
			else
			{
				// 截取输出至外部接口，放弃控制权
				sl_output.output(sl_env.dis.buff);
			}
		#else
			// 输入字符串处理，以回车结束 
			sl_cmd_para(sl_env.dis.buff);
		#endif
		}
		sl_newline();
		sl_printf(SL_HEADER);
	}
	return 0;
}

/**
 * @brief 清空环境缓存区
 * 
 */
static void sl_clear_env(void)
{
	int i = 0;
	memset(sl_env.dis.buff,0,SL_HIS_FIFO_LEN);	
	sl_env.dis_cursor = 0;
	sl_env.his_cursor = 0;
	sl_env.wkey_val =0;
	sl_env.dis.len = 0;
	for ( ; i<SL_HIS_FIFO_NUM;i++)
	{
		memset(sl_env.his[i].buff,0,SL_HIS_FIFO_LEN);	
		sl_env.his[i].len = 0;
	}
}

/**
 * @brief 指令汇总
 * 
 * @return int 返回指令总数
 */
static int sl_collect_cmds(void)
{
	#if (SL_LS2K1000_EX)
	int i = 0;
	/*用户注册指令*/
	int user_cmds_num = ((int )__stop_cmd_list-(int)__start_cmd_list)/sizeof(sline_cmd_code_t);
	if(sl_cmds_num + user_cmds_num > SL_CMDS_LEN)
	{
		sl_printf("cmds is too much\r\n");
		return -1;
	}
	for(i = 0;i<user_cmds_num;i++)
	{
		int name_len = strlen(sl_cmd_list[i].name);
		int desc_len = strlen(sl_cmd_list[i].desc);
		memcpy(sl_cmds[sl_cmds_num+i].name,sl_cmd_list[i].name,(name_len>SL_CMD_NAME_LEN)?SL_CMD_NAME_LEN:name_len);
		memcpy(sl_cmds[sl_cmds_num+i].desc,sl_cmd_list[i].desc,(desc_len>SL_CMD_NAME_LEN)?SL_CMD_NAME_LEN:desc_len);
		sl_cmds[sl_cmds_num+i].func = sl_cmd_list[i].func;
	}
	sl_cmds_num += user_cmds_num;
	#endif
	return sl_cmds_num;
}

/**
 * @brief sline 开始打印输出内容
 * 
 */
static void sl_start_print( void )
{
	#if (SL_START_PRINT >= 2)
	sl_printf("     ______    __        __   _______   _______  \r\n");
	sl_printf("    / ____/   / /       / /  / ___  /  / _____/ 	\r\n");
	sl_printf("   / /____   / /       / /  / /  / /  / /___  	\r\n");
	sl_printf("  /____  /  / /       / /  / /  / /  / ____/ 	\r\n");
	sl_printf(" _____/ /  / /____   / /  / /  / /  / /____  	\r\n");
	sl_printf("/______/  /______/  /_/  /_/  /_/  /______/ 		\r\n");
	#endif
	#if (SL_START_PRINT >= 1)
	sl_printf("wellcome to use sline!\r\n");
	sl_printf("version: %s \r\nauthor: zxl\r\n",SL_VERSION);
	#endif
}
/**
 * @brief 创建sline对象
 * 
 * @param sl_func 注册的基本函数
 * @return int 0：正常 -1:失败
 */
int sl_create(sl_register_func_t * sl_func)
{
	sl_clear_env();

	if(sl_func == NULL)
	{
		return -1;
	}

	sl_env.func.getc = sl_func->getc;
	sl_env.func.putc = sl_func->putc;
	sl_env.status = 0;
	/* 预制命令 */
#if (!SL_LS2K1000_EX)
	sl_cmd_export_pre("help",sl_show_allcmd,"Display all of cmds.");
#endif
	/* 收集注册指令 */
	sl_cmds_num = sl_collect_cmds();
	/* 开始打印 */
	sl_start_print();
	sl_printf(SL_HEADER);
	return 0;
}

/**
 * @brief 关闭sline对象
 * 
 */
void sl_delete(void)
{
	sl_env.status = -1;
	sl_clear_env();
}
/**
 * @brief LS2K1000环境的预制指令
 * 
 */
#if (SL_LS2K1000_EX)
	#define help sl_show_allcmd
	SL_CMD_EXPORT(help,Display all of cmds.)
#endif
